home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Tech Arsenal 1
/
Tech Arsenal (Arsenal Computer).ISO
/
tek-04
/
pxewin.zip
/
BROWSER.CPP
< prev
next >
Wrap
C/C++ Source or Header
|
1992-01-17
|
27KB
|
1,097 lines
// BROWSER_HPP //
// Contents ----------------------------------------------------------------
//
// This header contains members for the following classes and
// structures:
//
// 1. Class PXListBox. Redefines listboxes for browsing PDOX tables.
//
// 2. Stucture LB_PARM. Stores the parameters for all the list boxes.
//
// 3. Class DBDISPLAY. Displays the database in page format with 20
// records per page.
//
// 4. Class PXScroller. Redifines the scroller for scrolling PDOX
// tables. The vertical scroll is all that is redefined.
//
// 5. Class Browser. Creates a browser window that is MDI complient.
//
// 6. Class BrowserFrame. Creates a MDI frame for creating browser
// windows.
//
// End ---------------------------------------------------------------------
// External Reference Name For This Header ---------------------------------
#ifndef BROWSER_CPP
#define BROWSER_CPP
// End ---------------------------------------------------------------------
// Interface Dependencies --------------------------------------------------
#ifndef BROWSER_HPP
#include "browser.hpp"
#endif
// member VScroll of PXScroller //
void PXScroller::VScroll(WORD ScrollEvent,int ThumbPos)
{
// In case the number of records changes.
my_display->my_table->NumRecs();
SetRange(my_display->RetSum(),
my_display->EngDataPtr->num_recs - 1);
switch(ScrollEvent)
{
case SB_LINEDOWN:
{
YPos++;
my_display->IncRec();
break;
}
case SB_LINEUP:
{
YPos--;
my_display->DecRec();
break;
}
case SB_THUMBPOSITION:
{
YPos = ThumbPos;
my_display->FillBoxes(YPos + 1);
break;
}
case SB_PAGEDOWN:
{
YPos += PAGE_SIZE;
my_display->FillBoxes(YPos + 1);
break;
}
case SB_PAGEUP:
{
YPos -= PAGE_SIZE;
my_display->FillBoxes(YPos + 1);
break;
}
}
// Scroll bars should reflect current database position.
YPos = my_display->RetCurRec() - 1;
// EndView will set the scroller to the desired position
EndView();
}
// Summary -----------------------------------------------------------------
//
// Redefine vertical scroll bars to allow scrolling through a table.
//
// Parameters
//
// ScrollEvent. This is the scroll event parameters.
//
// Thumbpos. The thumb position of the scroll bar.
//
// Return Value
//
// None.
//
// Functional Description
//
// Each vertical scroll event is redefined here. Each increment of
// YPos cooresponds to one record in the database. First check and
// make sure the range is set according to the number of records in
// the table.
//
// The following is a summary of the scrolling events and how they are
// handled:
//
// SB_LINEDOWN. Increment YPos. Call your display increment
// record routine.
//
// SB_LINEUP. Decrement YPos. Call your display decrement record
// routine.
//
// SB_THUMBPOSITION. Set YPos to thumb position. Call your display
// routine for filling the boxes. Record position starts with record
// 1 so you have to add 1 to the YPos to get the record number.
//
// SB_PAGEDOWN. Add the page size to YPos. Call your display routine
// for filling the boxes.
//
// SB_PAGEUP. Subtract the page size from YPos. Call you display
// routine for filling the boxes.
//
//
// You will notice that we have not done any range checks on YPos.
// Range checking is done in the display routine. So we call the
// display routine to give us the current record for YPos. This will
// be range checked. Then we can call EndView to set the final scroll
// position.
//
// End ---------------------------------------------------------------------
// constructor DBDISPLAY //
inline DBDISPLAY::DBDISPLAY()
{
my_parm = NULL;
UpdateFlag = 1;
}
// Description -------------------------------------------------------------
//
// Constructor for DBDISPLAY. Set my_parm to NULL, UpdateFlag for
// display updates and create a new windows class object.
//
// End ---------------------------------------------------------------------
// Description -------------------------------------------------------------
//
// Sets cursor to normal type cursor.
//
// End ---------------------------------------------------------------------
// member FillBoxes //
void DBDISPLAY::FillBoxes(RECORDNUMBER rec)
{
int i; /* Field index */
int j; /* Record index */
int sel; /* Temperary item selection
variable */
int upper_limit; /* Number of records to
get */
char* temp;
// Set mouse cursor to wait
SendMessage(AP->Parent->HWindow,WM_SETWTCUR,0,0);
// Reset update flag
UpdateFlag = 0;
// Check and see if record number is less than first record.
if(rec < 1)
rec = 1;
// Get the number of records in the table.
my_table->NumRecs();
// If you have less records then a PAGE_SIZE, then set your first
// record of the page to the first record in the database. Set the
// upper limit of the last record you will get to the number of
// records in the database.
if(EngDataPtr->num_recs < PAGE_SIZE)
{
upper_limit = EngDataPtr->num_recs;
top_rec = 1;
}
else
{
// Else, set the upper limit to the page size.
upper_limit = PAGE_SIZE;
// If you are less than a page size away from the end of the
// database, set the top record to the number of records in
// the database minus the size of the page.
if(rec + PAGE_SIZE > EngDataPtr->num_recs){
top_rec = EngDataPtr->num_recs - PAGE_SIZE + 1;
sel = rec - top_rec;
}
else
{
// Else, leave the top record value at the parameter
// setting.
top_rec = rec;
sel = 0;
}
}
// Empty the list boxes.
for(i = 0;i < EngDataPtr->num_fields;i++)
my_parm[i]->my_box->ClearList();
my_record->GoTo(top_rec);
for(j = 0;j < upper_limit;j++)
{
// Get the record data into the record transfer buffer.
my_record->Get();
for(i = 0;i < EngDataPtr->num_fields;i++)
{
// Get the field data and put in into the list box.
temp = PXDIS::Get(i);
my_parm[i]->my_box->AddString(temp);
}
// Go to the next record.
my_record->RecNext();
}
// Set item out of bounds so it will pass through range check ok
item = -1;
// Set update flag
UpdateFlag = 1;
// Select the item
SelRecord(sel);
// Set mouse cursor to normal
SendMessage(AP->Parent->HWindow,WM_SETNMCUR,0,0);
}
// Summary -----------------------------------------------------------------
//
// This member fills the list boxes with data from the database.
//
// Parameters
//
// rec. This is the record number of the top record in the list boxes.
//
// Return Value
//
// None.
//
// Functional Description
//
// 1. Set the mouse cursor to the wait cursor.
//
// 2. Reset the UpdateFlag so updates will not occur until the list
// boxes are refilled. This flag will be read by the PXListBox
// routine to make sure Updates as they would normally when WMPaint is
// called (TControl version of WMPaint).
//
// 3. Range check rec. If it is less than the first record, reset it
// to the first record. For a table that is less the a PAGE_SIZE, limit
// the upperbound accordingly. Else the upperbound is the PAGE_SIZE.
// If rec plus PAGE_SIZE is greater than the number of records then set
// top_rec to PAGE_SIZE less than the number of records and your
// selection is somewhere in between. Else leave rec untouched and
// set you selection to the top record.
//
// 4. Empty the list boxes.
//
// 5. Fill the list boxes.
//
// 6. You need to set the item number out of bounds so the selection
// routine sees that the selection has changed.
//
// 7. Set the UpdateFlag to allow updates and call the selection
// routine.
//
// 8. Set the mouse cursor to normal.
//
// End ---------------------------------------------------------------------
// member SetUp //
int DBDISPLAY::SetUp(Browser *AParent)
{
char *header; /* Temp location for header
*/
int hd_len; /* Length of header */
int char_size; /* Is the number of ASCII
characters it takes to
represent the field. */
int i; /* Field index */
item = -1; /* Set item pointer to a
nonselected location */
EngDataPtr->name = AParent->name;
AP = AParent;
sum = 1;
// Setup database
PXDIS::SetUp(0,0,EXISTS,0);
// Make an array of field parameter pointers
my_parm = new LB_PARM* [EngDataPtr->num_fields];
for(i = 0;i < EngDataPtr->num_fields;i++){
my_parm[i] = new LB_PARM;
// Set up a field pointer
my_parm[i]->my_field = my_field[i];
// If parameter set is the first set, initialize x
// coordinate of the list box independently.
if(i == 0)
my_parm[i]->x = 2;
else{
// Else, the list box coordinate depends on
// where the previous list box ends.
my_parm[i]->x = my_parm[i - 1]->x +
my_parm[i - 1]->w + 2;
}
// Precalc some things we will be using more than once.
header = my_parm[i]->my_field->RetName();
hd_len = strlen(header);
char_size = my_parm[i]->my_field->RetCharSize();
// The width of the list box is calculated. It is
// the character size of the field times the
// character width unless the field header is larger.
if(char_size > hd_len){
my_parm[i]->w = char_size*CHAR_WIDTH;
sum += char_size;
}
else{
my_parm[i]->w = hd_len*CHAR_WIDTH;
sum += hd_len;
}
// Set up the list box.
my_parm[i]->my_box = new PXListBox(AParent,i,
my_parm[i]->x,20,my_parm[i]->w,16.5*PAGE_SIZE);
// Set up header for your list boxes
my_parm[i]->my_header = new TStatic(AParent,-1,
header,my_parm[i]->x,1,200,15,hd_len + 1);
}
return PXSUCCESS;
}
// Summary -----------------------------------------------------------------
//
// This sets up the database for displaying all the fields.
//
// Parameters
//
// AParent. Needs the parent window object to construct the list boxes
// and the field headers.
//
// Functional Description
//
// 1. Call the SetUp routine for setting up the database.
//
// 2. Construct a parameter array for storing list box info.
//
// 3. Construct a for loop that will initialize all the fields for
// display. The information necessary for storing the list box data is
// saved in the LB_PARM structure. Placement locations and sizes of
// each list box are calculated. Headers for each field are placed
// at the top of the list box.
//
// End ---------------------------------------------------------------------
// Destructor ~DBDISPLAY //
DBDISPLAY::~DBDISPLAY()
{
int i; /* Field index */
// if ther is no parameter pointer, then the number of fields is
// unknown so set to zero.
if(!my_parm)
EngDataPtr->num_fields = 0;
for(i = 0;i < EngDataPtr->num_fields;i++)
delete my_parm[i];
delete my_parm;
}
// End ---------------------------------------------------------------------
// Summary -----------------------------------------------------------------
//
// Kills all buffers used in DBDISPLAY.
//
// End ---------------------------------------------------------------------
// member SelRecord //
void DBDISPLAY::SelRecord(int ITEM)
{
int i; /* Field index */
// Range check item
if(ITEM >= PAGE_SIZE)
ITEM = PAGE_SIZE - 1;
if(ITEM < 0)
ITEM = 0;
if(item == ITEM)
{
if(item == 0)
ScrollDwn();
else{
if(item == PAGE_SIZE - 1)
ScrollUp();
}
}
// Select items if you are somewhere within a page or your have
// incremented past the page but you are not at the last record.
// For a decrement before the page you don't need to select since
// you are doing and insert at the first record.
if((item == PAGE_SIZE - 1) || item != ITEM)
{
for(i = 0;i < EngDataPtr->num_fields;i++)
{
my_parm[i]->my_box->SetSelIndex(ITEM);
}
}
item = ITEM;
}
// Summary -----------------------------------------------------------------
//
// Selects the record cooresponding to the item number in the list boxes
//
// Parameters
//
// item. This is the list box item number.
//
// Return Value
//
// None.
//
// Description
//
// 1. The item number is range checked. If the item number is greater
// then the page size then it is set to the page size. If the item
// number is less than the first item number, it is set to the first
// item.
//
// 2. If the old item number is equal to the new item number then check
// for a scroll up or down situation. It is scroll up if item is the
// first item, scroll down if item is the last item in the list box.
//
// 3. If item selected is at the end of the list or somewhere in
// the middle of the list, then set all the lists to the same item.
//
// End ---------------------------------------------------------------------
// member IncRec of DBDISPLAY //
void DBDISPLAY::IncRec()
{
SelRecord(item + 1);
}
// Summary -----------------------------------------------------------------
//
// Increments an item in the list boxes.
//
// End ---------------------------------------------------------------------
// member DecRec of DBDISPLAY //
void DBDISPLAY::DecRec()
{
SelRecord(item - 1);
}
// Summary -----------------------------------------------------------------
//
// Decrements an item in the list boxes.
//
// End ---------------------------------------------------------------------
// member ScrollUp //
void DBDISPLAY::ScrollUp()
{
int i; /* Field index */
// Make sure your not already at the last record in the table.
// Note that we specifically call for the number of records since
// this may change as we add and delete records from the database.
my_table->NumRecs();
if(top_rec + PAGE_SIZE <= EngDataPtr->num_recs){
// Go to the new record and get data
my_record->GoTo(top_rec + PAGE_SIZE);
my_record->Get();
for(i = 0;i < EngDataPtr->num_fields;i++)
{
// Delete the first item in the list
my_parm[i]->my_box->DeleteString(0);
// Add the new next item to the list
my_parm[i]->my_box->AddString(PXDIS::Get(i));
}
top_rec++;
}
}
// Summary -----------------------------------------------------------------
//
// This scrolls the display up by one record.
//
// Parameters
//
// None.
//
// Return Value
//
// None.
//
// Description
//
// 1. Do a boundary check and make sure your not at the last record.
//
// 2. Go to the last record in the list and get the data.
//
// 3. For all the lists, delete the first item in the list and add the
// new data to the end of the list.
//
// 4. Increment the top record pointer.
//
// End ---------------------------------------------------------------------
// member ScrollDwn //
void DBDISPLAY::ScrollDwn()
{
int i; /* Field index */
// Make sure your not already at the first record in the table
if(top_rec > 1){
// Go to the new record and get data
top_rec--;
my_record->GoTo(top_rec);
my_record->Get();
for(i = 0;i < EngDataPtr->num_fields;i++)
{
// Delete the last item in the list
my_parm[i]->my_box->DeleteString(PAGE_SIZE - 1);
// Add the new text item to the begining of the list
my_parm[i]->my_box->InsertString(PXDIS::Get(i),0);
}
}
}
// Summary -----------------------------------------------------------------
//
// Scrolls the display down one record.
//
// Parameters
//
// None.
//
// Return Value
//
// None.
//
// Description
//
// 1. Make sure you are not at the first record in the database.
//
// 2. Decrement the top record pointer.
//
// 3. Go to the top record and get the data.
//
// 4. For all the fields, delete the last string in the list and insert
// the new data at the first string position in the list.
//
// End ---------------------------------------------------------------------
// member Browser //
Browser::Browser(PTWindowsObject AParent,int):TWindow(AParent,"")
{
// Create a new DBDISPLAY
name = new char[MAXPATH];
my_display = new DBDISPLAY;
strcpy(name,"*.db"); /* Construct a file mask for
the file dialog */
// Execute file dialog
if(GetApplication()->ExecDialog(
new TFileDialog(this,SD_FILEOPEN,
name)) == IDOK)
{
flag = EXISTS;
// Store a copy of the database name to the window header
Title = _fstrdup(name);
if(*Title == NULL)
flag = NOTEXISTS;
}
else
flag = NOTEXISTS;
// If database does not exist, NULL out db and return
if(flag == NOTEXISTS)
return;
flag = EXISTS;
// Get the display for the database setup.
my_display->SetUp(this);
if(my_display->RetPXError() != PXSUCCESS)
{
MessageBox(HWindow,
my_display->RetPXErrorMsg(),
"Database Error",MB_OK);
flag = NOTEXISTS;
return;
}
// Set up scroll bars.
Attr.Style |= WS_VSCROLL | WS_HSCROLL;
// Point the Scroller to the custom database scroller. Vertical
// scroll will be redifined.
Scroller = new PXScroller(this,8,15,80,60);
}
// Summary -----------------------------------------------------------------
//
// Creates a browser window for browsing a Paradox database.
//
// Parameters
//
// AParent. This would be the MDI frame window.
//
// The int is for the window count since each window object is put into
// a linked list.
//
// Functional Description
//
// 1. Create a new name buffer for the database name.
//
// 2. Call the File dialog box. If file exists, set flag to EXISTS.
// Save a copy of the file name to the Title of the window data member.
// If the Title is NULL or the file dialog does not return IDOK then
// set existance flag to NOTEXIST.
//
// 3. If flag is set to NOTEXIST, return to BrowserFrame.
//
// 4. Set up the database.
//
// 5. If an error occured in the set up, display the error, set the
// flag to NOTEXIST and return to the MDI.
//
// 6. Set the styles for the scroll bars and construct the Scroller.
//
// End ---------------------------------------------------------------------
// destructor Browser //
inline Browser::~Browser()
{
// Dispatch a message to the BrowserFrame that you have killed
// yourself.
SendMessage(Parent->HWindow,WM_CHKCHILD,0,0);
}
// Summary -----------------------------------------------------------------
//
// Delete database name and tell the BrowserFrame to check its children.
//
// End ---------------------------------------------------------------------
// constructor PXListBox //
PXListBox::PXListBox(Browser *AParent,
int AnId,int X,int Y,int W,int H,
PTModule AModule):
TListBox((PTWindowsObject)AParent,
AnId,X,Y,W,H,AModule)
{
// Copy display pointer
my_display = AParent->my_display;
// Disable item sort.
Attr.Style &= ~LBS_SORT;
}
// Summary -----------------------------------------------------------------
//
// Redefines and sets up list boxes for the browser display.
//
// Parameters
//
// Parameters are as they are ussually for list boxes except the
// parent window is of type Browser. This must be caste to a
// PTWindowsObject type.
//
// Functional Description
//
// Caste the parent window to my display object so we can call display
// routines. Set the style so that the list boxes are not sorted.
//
// End ---------------------------------------------------------------------
void PXListBox::LBNSelChange(RTMessage)
{
my_display->SelRecord(GetSelIndex());
}
void PXListBox::WMPaint(RTMessage Msg)
{
if(my_display->RetFlag())
TControl::WMPaint(Msg);
}
// Description -------------------------------------------------------------
//
// Redefine WMPaint so that list boxes are not drawn when the
// the Update flag is reset. Since the OWL will do screen refresh
// on the list boxes for each new entrie in the box, it is better
// to do a paint after the list has completely been updated.
//
// End ---------------------------------------------------------------------
// member SetupWindow //
void Browser::SetupWindow()
{
TWindow::SetupWindow();
// You want to set the x scroller range depending on how many
// total characters you have in all the fields. The y
// scroller range is determined by how many records you have
// in the database.
my_display->my_table->NumRecs();
Scroller->SetRange(my_display->RetSum(),
my_display->EngDataPtr->num_recs - 1);
// Get the data from the database and fill up list boxes
// with it and select the first entrie.
my_display->FillBoxes(1);
}
// Summary -----------------------------------------------------------------
//
// Sets up browser window
//
// Parameters
//
// None.
//
// Return Value
//
// None.
//
// Description
//
// Calls TWindows set up. Sets the range on the scroll bar to
// conform with the database ranges and fills the list boxes with
// the data.
//
// End ---------------------------------------------------------------------
// member CursorWait of BrowserFrame //
inline void BrowserFrame::CursorWait(RTMessage)
{
MyClass->hCursor = LoadCursor(NULL,IDC_WAIT);
SetCursor(MyClass->hCursor);
}
// Description -------------------------------------------------------------
//
// Sets cursor to wait type cursor.
//
// End ---------------------------------------------------------------------
// member CursorNormal of BrowserFrame //
inline void BrowserFrame::CursorNormal(RTMessage)
{
MyClass->hCursor = LoadCursor(NULL,IDC_ARROW);
SetCursor(MyClass->hCursor);
}
// member MenuItemDisable of BrowserFrame //
inline void BrowserFrame::MenuItemDisable(int item)
{
HMENU hMenu; /* Menu handle */
// Get the menu handle
hMenu = GetMenu(HWindow);
// Disable menu item.
EnableMenuItem(hMenu,item,MF_GRAYED);
}
// Summary -----------------------------------------------------------------
//
// Disables selected menu item.
//
// Parameter
//
// item. Is the menu item number to disable.
//
// End ---------------------------------------------------------------------
// member MenuItemEnable of BrowserFrame //
inline void BrowserFrame::MenuItemEnable(int item)
{
HMENU hMenu; /* Menu handle */
// Get the menu handle
hMenu = GetMenu(HWindow);
// Enable menu item.
EnableMenuItem(hMenu,item,MF_ENABLED);
}
// Summary -----------------------------------------------------------------
//
// Disables selected menu item.
//
// Parameter
//
// item. Is the menu item number to disable.
//
// End ---------------------------------------------------------------------
// member GetWindowClass of BrowserFrame //
inline void BrowserFrame::GetWindowClass(WNDCLASS& AWndClass)
{
TWindow::GetWindowClass(AWndClass);
MyClass = &AWndClass;
}
// Summary -----------------------------------------------------------------
//
// Set up windows class object.
//
// End ---------------------------------------------------------------------
// constructor BrowserFrame //
inline BrowserFrame::BrowserFrame(LPSTR ATitle):
TMDIFrame(ATitle,"COMMANDS")
{
// Create a windows class buffer
MyClass = new WNDCLASS;
// Open the PXEngine for windows in single client mode
engine = new PXI("me",PXSINGLECLIENT);
if((error = engine->RetPXError()) != PXSUCCESS)
{
MessageBox(HWindow,engine->RetPXErrorMsg(),
"Database Error",MB_OK);
CloseWindow();
}
}
// Summary -----------------------------------------------------------------
//
// Create a MDI Browser frame.
//
// Parameters
//
// Pass of the frame title and commands menu to the MDI window.
//
// Description
//
// Initialize engine in single client mode. If you get an error, let
// the message box say what it is and close the window.
//
// End ---------------------------------------------------------------------
// member CreateChild of BrowserFrame //
inline PTWindowsObject BrowserFrame::CreateChild()
{
Browser *NewChild; /* New child pointer */
// Make a new child window
NewChild = new Browser(this,GetChildCount()+1);
// If the database exists, show it
if(NewChild->RetFlag() == EXISTS){
// Enable save menus
MenuItemEnable(CM_FILESAVE);
MenuItemEnable(CM_FILESAVEAS);
return GetApplication()->MakeWindow(NewChild);
}
// else kill the window and return NULL
delete NewChild;
return NULL;
}
// Summary -----------------------------------------------------------------
//
// Creates a new Browser window.
//
// Return Value
//
// Returns pointer to Browser window NewChild
//
// Functional Description
//
// 1. Initialize a new child window Browser.
//
// 2. If the new child exists, make the new window.
//
// 3. Else kill the child and return NULL.
//
// End ---------------------------------------------------------------------
// destructor BrowserFrame //
inline BrowserFrame::~BrowserFrame()
{
CloseChildren();
delete engine;
delete MyClass;
}
// Summary -----------------------------------------------------------------
//
// Call CloseChildren to close any open children. Delete the engine
// object.
//
// End ---------------------------------------------------------------------
// member SetupWindow of BrowserFrame //
inline void BrowserFrame::SetupWindow()
{
TMDIFrame::SetupWindow();
Show(SW_SHOWMAXIMIZED);
}
// Summary -----------------------------------------------------------------
//
// Call the MDI frame setup and set maximized show.
//
// End ---------------------------------------------------------------------
// member GetChildCount of BrowserFrame //
inline int BrowserFrame::GetChildCount()
{
int Count = 0;
ForEach(CountChild,&Count);
return Count;
}
// Summary -----------------------------------------------------------------
//
// Lets the Frame window count the children.
//
// End ---------------------------------------------------------------------
// member CreateBrowser of BrowserFrame //
inline void BrowserFrame::CreateBrowser(RTMessage)
{
CreateChild();
}
// Summary -----------------------------------------------------------------
//
// Creates child window when command is dispatched.
//
// End ---------------------------------------------------------------------
// member CheckChildren of BrowserFrame //
inline void BrowserFrame::CheckChildren(RTMessage)
{
int count; /* Number of children */
count = GetChildCount();
if(count == 1)
{
MenuItemDisable(CM_FILESAVE);
MenuItemDisable(CM_FILESAVEAS);
}
}
// Summary -----------------------------------------------------------------
//
// Responds to a message sent by a Browser to check your children
//
// Parameters
//
// RTMessage. This is the message sent.
//
// Functional Description --------------------------------------------------
//
// Get the child count. If there are no children then disable the save
// menus.
//
// End ---------------------------------------------------------------------
#endif